package com.ddzj.scaffold.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ddzj.scaffold.dto.UserInfoDto;
import com.ddzj.scaffold.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author:yangzibo
 * @CreateTime:2024-04-13 23:34
 * @Description:
 * @Version:1.0
 **/
public class JWTUtil {
    private static final Logger logger = LoggerFactory.getLogger(JWTUtil.class);

    //私钥
    private static final String TOKEN_SECRET = "scaffold_6688";

    /**
     * 生成token，自定义过期时间 毫秒
     *
     * @param user
     * @return
     */
    public static String generateUserToken(User user, Map<String, Object> claimMap) {
        return generateToken(buildUserInfoDto(user), 60 * 60 * 1, claimMap);
    }

    /**
     * 生成token，自定义过期时间 毫秒
     *
     * @param user
     * @return
     */
    public static String generateUserFlushToken(User user, Map<String, Object> claimMap) {
        return generateToken(buildUserInfoDto(user), 60 * 60 * 2, claimMap);
    }

    public static UserInfoDto buildUserInfoDto(User user){
        UserInfoDto userInfoDto = new UserInfoDto();
        userInfoDto.setId(user.getId());
        userInfoDto.setAccount(user.getAccount());
        userInfoDto.setName(user.getName());
        return userInfoDto;
    }

    /**
     * 生成token，自定义过期时间 毫秒
     *
     * @param userTokenDTO
     * @return
     */
    public static String generateToken(UserInfoDto userTokenDTO, long ttlMillis, Map<String, Object> claimMap) {
        try {
            Date expireDate = new Date(System.currentTimeMillis() + ttlMillis * 1000);

            // 私钥和加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 设置头部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("Type", "Jwt");
            header.put("alg", "HS256");

            return JWT.create()
                    .withHeader(header)
                    //可以将基本信息放到claims中
                    .withClaim("token", JacksonUtil.obj2String(userTokenDTO))//userId
                    .withClaim("expandMap", claimMap)
                    .withExpiresAt(expireDate)
                    .withIssuedAt(new Date()) // 设置签发时间
                    .sign(algorithm);
        } catch (Exception e) {
            logger.error("generate token occur error, error is:{}", e);
            return null;
        }
    }

    /**
     * 检验token是否正确
     *
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
        try{
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            if(jwt != null){
                return true;
            }
        }catch (Exception e){
            logger.debug("解密失败：{}", token, e);
        }
        return false;
    }

    /**
     * 检验token是否正确
     *
     * @param token
     * @return
     */
    public static UserInfoDto parseToken(String token) {
        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);
        String tokenInfo = jwt.getClaim("token").asString();
        return JacksonUtil.string2Obj(tokenInfo, UserInfoDto.class);
    }

}
